import json
import re

from django.contrib.auth import logout
from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
from django_redis import get_redis_connection

from apps.carts.utils import merge_cart_cookie_to_redis
from apps.goods.models import SKU
from apps.users.models import User, Address
from meiduo_mall.settings.dev import logger
from meiduo_mall.utils.secret import SecretOauth

from meiduo_mall.utils.views import LoginRequiredJSONMixin


# 9. 浏览记录
class UserBrowseHistory(LoginRequiredJSONMixin, View):
    def post(self, request):
        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')

        # 2.校验参数
        try:
            SKU.objects.get(pk=sku_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        # 3.redis--pipeline--lrem --lpush --ltrim --execute
        # list user.id:[1, 2 ,3]
        client = get_redis_connection('history')
        save_key = 'history_%s' % request.user.id
        p1 = client.pipeline()
        # 去重
        p1.lrem(save_key, 0, sku_id)
        # 插入
        p1.lpush(save_key, sku_id)
        # 切片
        p1.ltrim(save_key, 0, 4)
        p1.execute()

        # 4.返回响应对象
        return JsonResponse({'code': 0, 'errmsg': '记录成功!'})

    def get(self, request):
        # 2.1 获取用户id  request.user.id
        save_key = "history_%s" % request.user.id
        # 2.2 链接redis     lrange(k , 0,-1)
        client = get_redis_connection('history')
        sku_ids = client.lrange(save_key, 0, -1)

        # 2.3 遍历 sku_ids --->SKU 找 sku 对象
        skus_list = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(pk=sku_id)
            skus_list.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price
            })

        # 下面 这段代码  从获取skus的角度是没有任何问题 ; 但是顺序不对
        # skus = SKU.objects.filter(pk__in=sku_ids)
        # for sku in skus:
        #     skus_list.append({
        #         'id': sku.id,
        #         'name': sku.name,
        #         'default_image_url': sku.default_image.url,
        #         'price': sku.price
        #     })

        # 2.4 json([{}])
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'skus': skus_list})


# 8.增加收货地址
class CreateAddressView(LoginRequiredJSONMixin, View):
    def post(self, request):

        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 2.校验参数  -判空 --判正则

        # 3.增加
        try:
            address = Address.objects.create(
                user=request.user,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,

                title=receiver,
                receiver=receiver,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email

            )

            # 判断用户  是否 设置 默认 地址
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()

        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '增加失败!'})

        # 4.address == >address_dict
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,

            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,

            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        return JsonResponse({'code': 0, 'errmsg': '增加成功!', 'address': address_dict})


# 7.激活邮箱
class VerifyEmailView(View):
    def put(self, request):
        # - 1.接收 token
        token = request.GET.get('token')

        if not token:
            return JsonResponse({'code': 400, 'errmsg': 'token缺少'})

        # - 2.解密
        data_dict = SecretOauth().loads(token)

        # - 4.去数据库对比 user_id,email
        try:
            user = User.objects.get(pk=data_dict.get('user_id'), email=data_dict.get('email'))
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数有误!'})

        # - 5.修改激活状态
        user.email_active = True
        user.save()

        return JsonResponse({'code': 0, 'errmsg': '激活成功!'})


# 6. 添加邮箱
class EmailView(LoginRequiredJSONMixin, View):
    def put(self, request):
        # 3.接收参数 email 校验 email正则
        json_dict = json.loads(request.body.decode())
        email = json_dict.get('email')

        # 4.修改User类 request.user.email = new_email
        request.user.email = email
        request.user.save()

        # 发邮件
        from apps.users.utils import generate_verify_email_url
        verify_url = generate_verify_email_url(request)
        from celery_tasks.email.tasks import send_verify_email
        send_verify_email.delay(email, verify_url)

        # 5. request.user.save()
        # 6.返回结果
        return JsonResponse({'code': 0, 'errmsg': 'OK'})


# 5.用户中心
class UserInfoView(LoginRequiredJSONMixin, View):
    def get(self, request):
        return JsonResponse({
            'code': 0,
            'errmsg': '个人中心',
            "info_data": {
                "username": request.user.username,
                "mobile": request.user.mobile,
                "email": request.user.email,
                "email_active": request.user.email_active
            }
        })


# 4.用户退出
class LogoutView(View):
    def delete(self, request):
        # 1.清除session
        logout(request)

        # 2.清除cookie--username
        response = JsonResponse({'code': 0, 'errmsg': '退出成功!'})
        response.delete_cookie('username')

        # 3.返回
        return response


# 3.用户登录
class LoginView(View):
    def post(self, request):
        # 1,接收参数,提取参数  json
        json_dict = json.loads(request.body.decode())
        username = json_dict.get('username')
        password = json_dict.get('password')
        remembered = json_dict.get('remembered')

        # 2，校验参数--判空  和 正则
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '参数不齐!'})

        # 1.多账号登录
        # if re.match('^1[3-9]\d{9}$', username):
        #     User.USERNAME_FIELD = 'mobile'
        # else:
        #     User.USERNAME_FIELD = 'username'

        # 3， 与数据库进行判断，看用户名和密码是否一致
        # authenticate判断登录 密码加密对比
        from django.contrib.auth import authenticate, login
        user = authenticate(request, username=username, password=password)
        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误!'})

        # 保持登录状态
        login(request, user)

        # 是否记住登录--本质---session 啥时候过期
        if remembered != True:
            # 不记住登录  登录就过期
            request.session.set_expiry(0)
        else:
            # 记住登录  2周就过期
            request.session.set_expiry(None)

        # 4，返回响应结果
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})

        # 合并购物车
        merge_cart_cookie_to_redis(request, response)

        response.set_cookie('username', user.username, max_age=24 * 14 * 3600)
        return response


# 2.注册功能实现
class RegisterView(View):
    def post(self, request):
        # 1.接收参数 json
        # json_bytes = request.body
        # json_str = json_bytes.decode() # 二进制  转换  json  转换字符串
        # json_dict = json.loads(json_str) # json_str --> dict
        json_dict = json.loads(request.body.decode())

        # 2.解析参数
        username = json_dict.get('username')
        password = json_dict.get('password')
        password2 = json_dict.get('password2')
        mobile = json_dict.get('mobile')
        sms_code = json_dict.get('sms_code')
        allow = json_dict.get('allow')

        # 3.校验参数—判空, 判正则
        # if not all([username, password, password2, mobile, sms_code, allow]):
        #     return JsonResponse({'code': 400, 'errmsg': '参数不齐!'})
        #
        # # 3.1 判断 用户名的正则
        # if not re.match('^[a-zA-Z0-9_-]{5,20}$', username):
        #     return JsonResponse({'code': 400, 'errmsg': '用户名格式有误!'})
        #
        # # 3.2 判断 密码的正则
        # if not re.match('^[a-zA-Z0-9_-]{8,20}$', password):
        #     return JsonResponse({'code': 400, 'errmsg': '密码格式有误!'})
        #
        # # 3.3 两次密码是否一致
        # if password2 != password:
        #     return JsonResponse({'code': 400, 'errmsg': '两次密码不一致!'})
        #
        # # 3.4 判断  mobile的正则
        # if not re.match('^1[3-9]\d{9}$', mobile):
        #     return JsonResponse({'code': 400, 'errmsg': '手机号格式有误!'})
        #
        # # 3.5 是否勾选同意
        # if allow != True:
        #     return JsonResponse({'code': 400, 'errmsg': '勾选同意!'})
        #
        # # - 1.接收 前端 短信验证码 sms_code = json_dict.get('sms_code') 上面有写
        # # - 2.获取 后台 短信验证码
        # redis_conn = get_redis_connection('verify_code')
        # sms_code_server = redis_conn.get('sms_%s' % mobile)
        # # - 3.校验 前端和后台 短信验证码
        # if not sms_code_server:
        #     return JsonResponse({'code': 400, 'errmsg': '短信验证码过期了'})
        # # sms_code_server --bytes--decode()
        # if sms_code != sms_code_server.decode():
        #     return JsonResponse({'code': 400, 'errmsg': '短信验证码有误!'})

        # 4.主核心思路—user增加
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': '注册失败!'})

        # 保持登录状态
        from django.contrib.auth import login
        login(request, user)

        # 5.返回json
        response = JsonResponse({'code': 0, 'errmsg': '注册成功!'})
        response.set_cookie('username', user.username, max_age=24 * 14 * 3600)
        return response


# 1.判断用户名是否重复
class UserCountView(View):
    def get(self, request, username):
        # ###### 1.接收参数 username
        # ###### 2.校验参数 是否为空 --正则判断
        # ###### 3.核心主逻辑:User.objects.filter(username=username).count()
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            logger.error(e)  # 这个日志 你觉得代码多 可以不写
            return JsonResponse({'code': 400, 'errmsg': '查询失败!'})

        # ###### 4.构建json数据 返回响应!
        return JsonResponse({'code': 0, 'errmsg': '查询成功!', 'count': count})
